MVVM প্যাটার্নে Data Binding একটি অত্যন্ত গুরুত্বপূর্ণ কৌশল, যা View এবং ViewModel এর মধ্যে ডেটা সিঙ্ক্রোনাইজেশন সহজ করে তোলে। Data Binding Techniques এবং Observable Collections এর মাধ্যমে ডেটার পরিবর্তনগুলি স্বয়ংক্রিয়ভাবে UI-তে প্রতিফলিত হয়, যা অ্যাপ্লিকেশনটির পারফরম্যান্স এবং ব্যবহারযোগ্যতা উন্নত করে।
এখানে Data Binding Techniques এবং Observable Collections এর ব্যাখ্যা দেওয়া হয়েছে।
Data Binding হল এমন একটি প্রক্রিয়া যার মাধ্যমে UI উপাদানগুলির (যেমন, টেক্সটবক্স, বাটন, লেবেল ইত্যাদি) সাথে ViewModel এর ডেটা সংযুক্ত করা হয়। এটি UI এবং ডেটা মাঝে সম্পর্ক তৈরি করে, এবং ViewModel থেকে UI উপাদানগুলিতে ডেটা পাঠানোর পাশাপাশি ব্যবহারকারীর ইনপুটও ViewModel-এ পাঠায়।
One-Way Binding:
<TextBox Text="{Binding UserName}" />
এখানে TextBox এর Text প্রপার্টি ViewModel এর UserName প্রপার্টির সাথে বাইন্ড করা হয়েছে। যখন UserName পরিবর্তিত হবে, তখন তা TextBox-এ প্রতিফলিত হবে।
Two-Way Binding:
<TextBox Text="{Binding UserName, Mode=TwoWay}" />
এখানে TextBox এর Text প্রপার্টি UserName প্রপার্টির সাথে বাইন্ড করা হয়েছে, এবং এই বাইন্ডিংটি TwoWay মোডে কাজ করবে। অর্থাৎ, TextBox এ ব্যবহারকারী ইনপুট দিলে তা স্বয়ংক্রিয়ভাবে ViewModel এ চলে যাবে।
One-Way to Source Binding:
<TextBox Text="{Binding UserName, Mode=OneWayToSource}" />
এখানে TextBox এর Text প্রপার্টি UserName এর সাথে বাইন্ড করা হয়েছে, তবে এটি শুধুমাত্র ViewModel থেকে View-এ ডেটা পাঠাবে না, বরং View থেকে ViewModel-এ ইনপুটও পাঠাবে।
Command Binding:
<Button Content="Submit" Command="{Binding SubmitCommand}" />
এখানে Button এর Command প্রপার্টি SubmitCommand এর সাথে বাইন্ড করা হয়েছে, যা ViewModel এর একটি কমান্ড।
ObservableCollection হল একটি বিশেষ ধরনের কোলেকশন, যা ViewModel-এ ব্যবহৃত হয়, যখন ডেটা পরিবর্তন হলে UI উপাদানগুলোকে আপডেট করতে হয়। এটি INotifyCollectionChanged ইন্টারফেস ইমপ্লিমেন্ট করে, যা কোলেকশনের মধ্যে কোন পরিবর্তন ঘটলে View-এ স্বয়ংক্রিয়ভাবে রিফ্রেশ হয়।
ObservableCollection সাধারণত তালিকা বা কোলেকশনের ডেটা ViewModel এর মধ্যে পরিবর্তন করা হলে তা UI-তে ম্যানেজ করতে ব্যবহৃত হয়। উদাহরণস্বরূপ, আপনি যদি একটি প্রোডাক্ট তালিকা ব্যবহার করেন এবং সেই তালিকায় একটি নতুন প্রোডাক্ট যুক্ত বা মুছে ফেলেন, তবে ObservableCollection তা UI-তে আপডেট করবে।
public class ProductViewModel
{
public ObservableCollection<Product> Products { get; set; }
public ProductViewModel()
{
Products = new ObservableCollection<Product>
{
new Product { Name = "Laptop", Price = 800 },
new Product { Name = "Phone", Price = 500 }
};
}
public void AddProduct(Product product)
{
Products.Add(product);
}
public void RemoveProduct(Product product)
{
Products.Remove(product);
}
}
এখানে:
<ListBox ItemsSource="{Binding Products}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding Price}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
এখানে:
ObservableCollection হলো একটি বিশেষ ধরনের কোলেকশন, যা MVVM প্যাটার্নে ডেটা বাইন্ডিংয়ের জন্য ব্যাপকভাবে ব্যবহৃত হয়। এটি একটি Collection এর মত, তবে এর একটি বিশেষ সুবিধা রয়েছে—যখনই কোলেকশনে কোনো পরিবর্তন হয় (যেমন, আইটেম যোগ, মুছে ফেলা, বা আপডেট করা), তখন সেই পরিবর্তন স্বয়ংক্রিয়ভাবে UI তে প্রতিফলিত হয়।
এটি INotifyCollectionChanged ইন্টারফেস ইমপ্লিমেন্ট করে, যার ফলে UI কে অবহিত করে যে কোলেকশনে কিছু পরিবর্তন হয়েছে।
এই গাইডে, আমরা দেখব কিভাবে ObservableCollection ব্যবহার করে ডায়নামিক ডেটা বাইন্ডিং তৈরি করা যায়।
ObservableCollection হল একটি বিশেষ ধরনের কোলেকশন যা System.Collections.ObjectModel নামস্পেসে পাওয়া যায় এবং এটি INotifyPropertyChanged ইন্টারফেসের মতো INotifyCollectionChanged ইন্টারফেস ইমপ্লিমেন্ট করে। এর মাধ্যমে কোলেকশনে কোনো পরিবর্তন ঘটলে, সেই পরিবর্তনটি UI তে স্বয়ংক্রিয়ভাবে রিফ্লেক্ট হয়।
এটি সাধারণত MVVM প্যাটার্নে ব্যবহার হয় যেখানে ViewModel-এ ডেটা পরিবর্তন করলে তা View-এ স্বয়ংক্রিয়ভাবে প্রতিফলিত হয়।
ধরা যাক, আমাদের একটি অ্যাপ্লিকেশন আছে যেখানে ObservableCollection ব্যবহার করে ListBox তে ডাইনামিকভাবে ডেটা প্রদর্শন করতে হবে।
প্রথমে, আমাদের একটি Model তৈরি করতে হবে, যা ডেটা ধারণ করবে। উদাহরণস্বরূপ, একটি Product
মডেল তৈরি করা যাক:
public class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
}
এখন, ViewModel তৈরি করতে হবে যেখানে আমরা ObservableCollection ব্যবহার করব। এটি Product মডেলের একটি লিস্ট ধারণ করবে এবং UI-এ ডাইনামিক ডেটা বাইন্ডিং করব।
public class ProductViewModel : INotifyPropertyChanged
{
private ObservableCollection<Product> _products;
public ObservableCollection<Product> Products
{
get { return _products; }
set
{
_products = value;
OnPropertyChanged(nameof(Products));
}
}
public ProductViewModel()
{
// কোলেকশন ইনিশিয়ালাইজ করা
Products = new ObservableCollection<Product>
{
new Product { Name = "Laptop", Price = 50000 },
new Product { Name = "Smartphone", Price = 30000 },
new Product { Name = "Tablet", Price = 20000 }
};
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
এখানে ObservableCollection হল আমাদের ডেটা কোলেকশন, যা ViewModel তে থাকছে এবং UI-তে ডাইনামিকভাবে বাইন্ড হবে।
এখন, XAML ফাইল এ ViewModel-এর সাথে Data Binding করতে হবে। আমরা একটি ListBox ব্যবহার করব যেখানে ObservableCollection এর ডেটা প্রদর্শিত হবে।
<Window x:Class="DynamicDataBindingExample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Dynamic Data Binding Example" Height="350" Width="525">
<Window.DataContext>
<local:ProductViewModel />
</Window.DataContext>
<Grid>
<ListBox ItemsSource="{Binding Products}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}" FontWeight="Bold"/>
<TextBlock Text="{Binding Price}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
এখানে, ListBox এর ItemsSource
প্রপার্টি Products প্রপার্টির সাথে বাইন্ড করা হয়েছে। যখন ViewModel-এ Products কোলেকশনে কোনো পরিবর্তন হবে (যেমন নতুন প্রোডাক্ট যোগ করা বা মুছে ফেলা), তখন এটি UI তে স্বয়ংক্রিয়ভাবে প্রতিফলিত হবে।
এখন, ধরুন আমাদের অ্যাপ্লিকেশনে একটি বোতাম রয়েছে যার মাধ্যমে আমরা ডেটা আপডেট বা নতুন আইটেম যোগ করতে পারি:
public void AddNewProduct()
{
Products.Add(new Product { Name = "Headphones", Price = 1500 });
}
যখনই AddNewProduct মেথড কল করা হবে, একটি নতুন প্রোডাক্ট ObservableCollection এ যোগ হবে এবং তা UI তে দেখানো হবে।
এখন, XAML এ একটি Button যোগ করা যাক, যার মাধ্যমে নতুন প্রোডাক্ট যোগ করা যাবে:
<Button Content="Add Product" Click="AddProduct_Click" />
এবং কোড বিহাইন্ডে:
private void AddProduct_Click(object sender, RoutedEventArgs e)
{
(this.DataContext as ProductViewModel).AddNewProduct();
}
এখানে, AddProduct_Click ইভেন্ট হ্যান্ডলার ViewModel এর AddNewProduct মেথড কল করে এবং নতুন আইটেম ObservableCollection এ যোগ হয়। কারণ এটি ObservableCollection ব্যবহার করছে, UI তে নতুন আইটেম স্বয়ংক্রিয়ভাবে প্রতিফলিত হবে।
ObservableCollection একটি শক্তিশালী টুল যা MVVM প্যাটার্নে ডায়নামিক ডেটা বাইন্ডিং সহজ করে তোলে। যখনই কোলেকশনে কোনো পরিবর্তন ঘটে, তা UI তে স্বয়ংক্রিয়ভাবে প্রতিফলিত হয়, যা অ্যাপ্লিকেশনের কার্যকারিতা এবং ব্যবহারকারীর অভিজ্ঞতা উন্নত করে। এটি ডেভেলপারদের UI এবং ViewModel এর মধ্যে যোগাযোগ সহজ ও পরিষ্কারভাবে পরিচালনা করতে সহায়ক।
Complex Data Binding এবং Nested Object Binding হল MVVM (Model-View-ViewModel) প্যাটার্নে View এবং ViewModel এর মধ্যে আরও জটিল এবং গহিনভাবে ডেটা বাইন্ডিং করার উপায়। এ দুটি কৌশল ব্যবহার করে আপনি আরও উন্নত এবং ডাইনামিক অ্যাপ্লিকেশন তৈরি করতে পারেন যেখানে ডেটার ভিতরের স্তরের তথ্যও View-এ সঠিকভাবে উপস্থাপন করা হয়।
Complex Data Binding হল এমন একটি প্রক্রিয়া, যেখানে ViewModel থেকে View-এ ডেটার বিভিন্ন স্তরের বা কমপ্লেক্স অবজেক্টের মান প্রদর্শন করা হয়। এর মাধ্যমে আপনি একাধিক প্রপার্টি বা উপাদান একটি নির্দিষ্ট UI উপাদানে বাইন্ড করতে পারেন। এর মধ্যে একাধিক উপাদান বা Collection থেকে ডেটা প্রদর্শন করা হতে পারে, যা UI তে সঠিকভাবে রেন্ডার হয়।
ধরা যাক, আমাদের একটি Product
Model আছে এবং সেই সাথে একটি Category
নামে আরও একটি Model রয়েছে, যা প্রতিটি প্রোডাক্টের ক্যাটাগরি দেখাবে।
Model:
public class Category
{
public string CategoryName { get; set; }
}
public class Product
{
public string ProductName { get; set; }
public decimal Price { get; set; }
public Category Category { get; set; }
}
এখন, যদি আমাদের ViewModel এ Product এর ডেটা থাকে এবং আমরা View-এ সেই ডেটার মান দেখাতে চাই, তাহলে আমরা Complex Data Binding ব্যবহার করব।
ViewModel:
public class ProductViewModel
{
public Product Product { get; set; }
public ProductViewModel()
{
Product = new Product
{
ProductName = "Laptop",
Price = 999.99m,
Category = new Category { CategoryName = "Electronics" }
};
}
}
View (XAML):
<TextBlock Text="{Binding Product.ProductName}" />
<TextBlock Text="{Binding Product.Price}" />
<TextBlock Text="{Binding Product.Category.CategoryName}" />
এখানে, TextBlock গুলি Product অবজেক্টের ভেতরে থাকা বিভিন্ন প্রপার্টি (যেমন ProductName, Price, এবং CategoryName) প্রদর্শন করছে। ViewModel থেকে View-এ কমপ্লেক্স ডেটা বাইন্ড করা হচ্ছে।
Nested Object Binding হল এমন একটি প্রক্রিয়া, যেখানে একটি Object অন্য একটি Object এর মধ্যে থাকে এবং আপনি সেই Nested Object এর প্রপার্টি বা ফিল্ডকে বাইন্ড করেন। এই ধরনের বাইন্ডিং ব্যবহৃত হয় যখন ViewModel এর মধ্যে Object এর অভ্যন্তরীণ স্তরের ডেটা থেকে View-এ তথ্য প্রদর্শন করতে হয়।
ধরা যাক, আমাদের Customer এবং Address নামের দুটি Model আছে, এবং Customer মডেলটি Address নামক একটি Nested Object ধারণ করে।
Model:
public class Address
{
public string Street { get; set; }
public string City { get; set; }
}
public class Customer
{
public string Name { get; set; }
public Address CustomerAddress { get; set; }
}
ViewModel:
public class CustomerViewModel
{
public Customer Customer { get; set; }
public CustomerViewModel()
{
Customer = new Customer
{
Name = "John Doe",
CustomerAddress = new Address { Street = "123 Main St", City = "New York" }
};
}
}
এখন, যদি আমরা Customer এর নাম এবং CustomerAddress এর ভেতরে থাকা স্ট্রিট এবং সিটি প্রদর্শন করতে চাই, তাহলে আমরা Nested Object Binding ব্যবহার করতে পারি।
View (XAML):
<TextBlock Text="{Binding Customer.Name}" />
<TextBlock Text="{Binding Customer.CustomerAddress.Street}" />
<TextBlock Text="{Binding Customer.CustomerAddress.City}" />
এখানে, Customer এর Name এবং CustomerAddress এর Street এবং City বাইন্ড করা হচ্ছে। এতে ViewModel এর Customer অবজেক্ট এবং এর ভেতরে থাকা Address অবজেক্টের প্রপার্টি দেখানো হচ্ছে।
MVVM প্যাটার্নে UI কাস্টমাইজেশন এবং ডেটার উপস্থাপন করার জন্য DataTemplate এবং ControlTemplate খুবই গুরুত্বপূর্ণ দুটি টেমপ্লেট। এই দুটি টেমপ্লেটের মাধ্যমে আপনি View এর কন্ট্রোল এবং ডেটার উপস্থাপন পরিবর্তন করতে পারবেন। নিচে DataTemplate এবং ControlTemplate এর ব্যবহারের বিস্তারিত ব্যাখ্যা দেওয়া হলো।
DataTemplate একটি XAML উপাদান যা UI তে ডেটা প্রদর্শনের জন্য ব্যবহৃত হয়। এটি Model এর ডেটাকে View এর জন্য উপযুক্তভাবে উপস্থাপন করতে সাহায্য করে। সাধারণত DataTemplate ব্যবহার করা হয় যখন আপনি ListView, ListBox, ComboBox অথবা অন্যান্য ডেটাবাউন্ড কন্ট্রোলের মধ্যে ডেটা উপস্থাপন করতে চান।
ধরা যাক, আপনার একটি Product ক্লাস আছে, যেখানে Name এবং Price প্রপার্টি রয়েছে। এই Product ডেটাকে ListBox-এ উপস্থাপন করতে DataTemplate ব্যবহার করা হবে।
public class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
}
এখন, XAML এ এই ডেটা DataTemplate ব্যবহার করে উপস্থাপন করা হবে:
<Window.Resources>
<DataTemplate x:Key="ProductTemplate">
<StackPanel>
<TextBlock Text="{Binding Name}" FontSize="18"/>
<TextBlock Text="{Binding Price, StringFormat={}{0:C}}" FontSize="14"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
<ListBox ItemsSource="{Binding Products}" ItemTemplate="{StaticResource ProductTemplate}" />
এখানে:
ControlTemplate হল একটি UI কন্ট্রোলের কাঠামো বা চেহারা সম্পূর্ণভাবে কাস্টমাইজ করার উপায়। এটি UI কন্ট্রোলের চেহারা পরিবর্তন করে, কিন্তু তার কার্যকারিতা বা লজিক অপরিবর্তিত রাখে। ControlTemplate ব্যবহারের মাধ্যমে, আপনি কন্ট্রোলের উপস্থাপন এবং স্টাইল সম্পূর্ণভাবে কাস্টমাইজ করতে পারেন।
ধরা যাক, আপনি একটি Button কন্ট্রোলের স্টাইল পরিবর্তন করতে চান, এবং সেই Button-এ কাস্টম গ্রাফিক্যাল উপস্থাপন করতে চান। আপনি এটি ControlTemplate এর মাধ্যমে করতে পারেন।
<Button Content="Click Me" Width="200" Height="50">
<Button.Template>
<ControlTemplate TargetType="Button">
<Grid>
<Ellipse Fill="LightBlue" Width="200" Height="50" />
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
</ControlTemplate>
</Button.Template>
</Button>
এখানে:
DataTemplate এবং ControlTemplate এর মধ্যে কিছু গুরুত্বপূর্ণ পার্থক্য রয়েছে:
এগুলি ব্যবহারের মাধ্যমে আপনি আপনার অ্যাপ্লিকেশনের UI এবং UX কে আরও ইউজার-ফ্রেন্ডলি এবং কাস্টমাইজড করতে পারবেন।
MVVM (Model-View-ViewModel) প্যাটার্নে Validation এবং Error Notification অত্যন্ত গুরুত্বপূর্ণ ভূমিকা পালন করে, কারণ এগুলি ইউজারের ইনপুটের সঠিকতা নিশ্চিত করে এবং ভুল ইনপুটের জন্য ইউজারকে যথাযথভাবে জানান দেয়। এই প্রক্রিয়াগুলি Model এবং ViewModel এর মধ্যে কাজ করে এবং View-এ এর ফলাফল প্রদর্শিত হয়।
Validation হল একটি প্রক্রিয়া যার মাধ্যমে ইউজারের ইনপুট যাচাই করা হয়, যাতে নিশ্চিত হওয়া যায় যে ইনপুটটি সঠিক এবং বৈধ। MVVM প্যাটার্নে, ইনপুট ভ্যালিডেশন সাধারণত ViewModel বা Model এ করা হয়, এবং ফলাফল View-এ Error Notification আকারে প্রদর্শিত হয়।
Data Annotations:
Required
, StringLength
, Range
, RegularExpression
ইত্যাদি।Data Annotations উদাহরণ:
public class Product
{
[Required(ErrorMessage = "Product name is required.")]
public string Name { get; set; }
[Range(0, 10000, ErrorMessage = "Price must be between 0 and 10,000.")]
public decimal Price { get; set; }
[Required(ErrorMessage = "Quantity is required.")]
[Range(1, 100, ErrorMessage = "Quantity must be between 1 and 100.")]
public int Quantity { get; set; }
}
IValidatableObject Interface:
Validate
প্রদান করে, যা প্রপার্টি ভ্যালিডেশনের সময় চেক করা হয় এবং যদি কোনো ত্রুটি থাকে, তাহলে সেই ত্রুটির বার্তা ফিরিয়ে দেয়।IValidatableObject উদাহরণ:
public class Product : IValidatableObject
{
public string Name { get; set; }
public decimal Price { get; set; }
public int Quantity { get; set; }
public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
if (Price < 0)
{
yield return new ValidationResult("Price cannot be negative", new[] { "Price" });
}
if (Quantity < 1 || Quantity > 100)
{
yield return new ValidationResult("Quantity must be between 1 and 100", new[] { "Quantity" });
}
}
}
Custom Validation Methods:
Custom Validation উদাহরণ:
public class LoginViewModel : INotifyPropertyChanged
{
private string _password;
private string _confirmPassword;
public string Password
{
get => _password;
set
{
_password = value;
OnPropertyChanged();
ValidatePasswords();
}
}
public string ConfirmPassword
{
get => _confirmPassword;
set
{
_confirmPassword = value;
OnPropertyChanged();
ValidatePasswords();
}
}
private void ValidatePasswords()
{
if (Password != ConfirmPassword)
{
// Set error message
ErrorMessage = "Passwords do not match.";
}
else
{
ErrorMessage = null;
}
}
public string ErrorMessage { get; set; }
}
Error Notification হল সেই প্রক্রিয়া, যার মাধ্যমে ইউজারের ভুল ইনপুট বা ভ্যালিডেশন সমস্যা সম্পর্কে তাকে অবহিত করা হয়। MVVM প্যাটার্নে, এই ত্রুটির বার্তা সাধারণত ViewModel থেকে View-এ পাঠানো হয় এবং ইউজারকে দেখানো হয়।
INotifyDataErrorInfo Interface:
INotifyDataErrorInfo উদাহরণ:
public class ProductViewModel : INotifyDataErrorInfo
{
private readonly Dictionary<string, List<string>> _errors = new();
public string Name { get; set; }
public decimal Price { get; set; }
public bool HasErrors => _errors.Any();
public IEnumerable<string> GetErrors(string propertyName)
{
if (_errors.ContainsKey(propertyName))
return _errors[propertyName];
return Enumerable.Empty<string>();
}
public void Validate()
{
if (string.IsNullOrEmpty(Name))
{
_errors["Name"] = new List<string> { "Name is required." };
}
else
{
_errors.Remove("Name");
}
if (Price < 0)
{
_errors["Price"] = new List<string> { "Price must be non-negative." };
}
else
{
_errors.Remove("Price");
}
OnPropertyChanged(nameof(HasErrors));
}
}
ErrorTemplate (UI Level):
ErrorTemplate উদাহরণ:
<Window.Resources>
<ControlTemplate x:Key="ErrorTemplate">
<Border BorderBrush="Red" BorderThickness="1">
<TextBlock Foreground="Red" Text="{Binding}" />
</Border>
</ControlTemplate>
</Window.Resources>
<TextBox Text="{Binding Name}" Width="200">
<TextBox.Template>
<ControlTemplate TargetType="TextBox">
<StackPanel>
<TextBox Name="TextBox" Text="{Binding Name}" />
<TextBlock Text="{Binding Path=ErrorMessage}" Foreground="Red"/>
</StackPanel>
</ControlTemplate>
</TextBox.Template>
</TextBox>
Validation এবং Error Notification MVVM প্যাটার্নে অ্যাপ্লিকেশনের ইউজার ইনপুট সঠিকতা নিশ্চিত করতে এবং ইউজারকে ত্রুটির সঠিক বার্তা প্রদর্শন করতে গুরুত্বপূর্ণ ভূমিকা পালন করে। Data Annotations, IValidatableObject, এবং INotifyDataErrorInfo ইন্টারফেসের মাধ্যমে আপনি আপনার অ্যাপ্লিকেশনে ইফেক্টিভ ভ্যালিডেশন ইমপ্লিমেন্ট করতে পারেন এবং Error Templates এবং Command এর মাধ্যমে ইউজারকে ত্রুটির বার্তা উপস্থাপন করতে পারেন।
common.read_more